﻿using Newtonsoft.Json;
using RXY_Mall.Api.Common;
using RXY_Mall.Api.Models;
using RXY_Mall.Core;
using RXY_Mall.Core.Tool;
using RXY_Mall.Data;
using RXY_Mall.Domain;
using RXY_Mall.Services.Goods;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using WebApi.OutputCache.V2;

namespace RXY_Mall.Api.Controllers
{
    /// <summary>
    /// 商品接口
    /// </summary>
    [RoutePrefix("Goods")]
    [ApiSecurityFilter]
    public partial class GoodsController : BaseApiController
    {
        private RXY_MallContext db;
        private GoodsService goodsService;

        /// <summary>
        /// 缓存时间 单位s
        /// </summary>
        public const int CACHETIME = 5;

        public GoodsController()
        {
            db = new RXY_MallContext();
            goodsService = new GoodsService();
        }

        /// <summary>
        /// 获得购物车历史
        /// </summary>
        /// <param name="user_id">用户ID</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetSearchHistory")]
        public async Task<Response<List<string>>> GetSearchHistory(int user_id)
        {
            Response<List<string>> result = new Response<List<string>>();
            result.code = 0;
            result.msg = "";
            try
            {
                var output = await db.gw_goods_searches
                                .Where(g => g.user_id == user_id)
                                .OrderByDescending(g => g.add_time)
                                .Select(g => new
                                {
                                    g.search
                                })
                                .ToListAsync();

                List<string> lst = new List<string>();
                if (output != null)
                {
                    foreach (var item in output)
                    {
                        if (!lst.Contains(item.search))
                        {
                            lst.Add(item.search);
                        }
                        if (lst.Count > 8)
                        {
                            break;
                        }
                    }
                }

                result.code = 1;
                result.msg = "获取成功";
                result.data = lst;
            }
            catch (Exception ex)
            {
                result.msg = ex.Message;
                result.code = 2;
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        #region 品牌
        /// <summary>
        /// 获得品牌列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("GetBrands")]
        [CacheOutput(ClientTimeSpan = 60, ServerTimeSpan = 60)]
        public async Task<Response<List<GetBrandsOutput>>> GetBrands(int user_id = 0)
        {
            Response<List<GetBrandsOutput>> result = new Response<List<GetBrandsOutput>>();
            try
            {
                var brands = await db.gw_base_brands
                    .Where(b => b.status == 1 && b.company_id == CompanyId)
                    .OrderByDescending(b => b.is_top)
                    .ThenBy(b => b.sort)
                    .ThenBy(b => b.name)
                    .Select(b => new GetBrandsOutput()
                    {
                        brand_id = b.id,
                        brand_name = b.name,
                        brand_logo = b.logo,
                        is_top = b.is_top,
                    }).ToListAsync();
                foreach (var item in brands)
                {
                    item.brand_logo = HostHelper.GetImgUrl(item.brand_logo);
                }
                result.code = 1;
                result.data = brands;
            }
            catch (Exception ex)
            {
                result.code = 2;
                result.msg = ex.Message;
                LogHelper.WriteLog(ex);
            }
            return result;
        }
        #endregion

        #region 商品分类
        /// <summary>
        /// 获取商品分类（第2批）
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("GetCategories")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public async Task<Response<List<GoodsCategoryOutput>>> GetCategories(int user_id = 0, GoodsType goods_type = GoodsType.Ordinary)
        {
            return await GetCategoriesByCategoryId(0, goods_type);
        }

        /// <summary>
        /// 获取子级商品分类
        /// </summary>
        /// <param name="category_id">商品分类ID</param>
        /// <param name="goods_type"></param>
        /// <returns></returns>
        private async Task<Response<List<GoodsCategoryOutput>>> GetCategoriesByCategoryId(int category_id, GoodsType goods_type)
        {
            Response<List<GoodsCategoryOutput>> result = new Response<List<GoodsCategoryOutput>>();
            result.code = 0;
            result.msg = "";
            result.data = null;

            try
            {
                var categoryBank = await db.gw_goods_categories.Where(c => c.status == 1 && c.company_id == CompanyId).ToListAsync();

                var GoodsCategory = categoryBank
                    .Where(c => c.parent_id == category_id);


                if (goods_type == GoodsType.Ordinary)
                {
                    GoodsCategory = GoodsCategory.Where(c => c.type == (int)GoodsType.Ordinary);
                }
                else if (goods_type == GoodsType.Memeber)
                {
                    GoodsCategory = GoodsCategory.Where(c => c.type == (int)GoodsType.Memeber);
                }
                var lstGoodsCategory = GoodsCategory.OrderByDescending(g => g.is_top).OrderBy(g => g.sort).ToList();

                if (lstGoodsCategory == null || lstGoodsCategory.Count() == 0)
                {
                    result.msg = "无数据";
                    return result;
                }

                List<GoodsCategoryOutput> output = new List<GoodsCategoryOutput>();
                foreach (var item in lstGoodsCategory)
                {
                    GoodsCategoryOutput goods = new GoodsCategoryOutput()
                    {
                        category_id = item.id,
                        name = item.name,
                        icon = HostHelper.GetImgUrl(item.icon),
                    };
                    var lstChildrenGoodsCategory = categoryBank.Where(g => g.parent_id == item.id).OrderBy(g => g.sort);

                    if (lstChildrenGoodsCategory != null)
                    {
                        goods.goods_categories = new List<GoodsCategoryOutput>();
                        foreach (var child in lstChildrenGoodsCategory)
                        {
                            GoodsCategoryOutput category = new GoodsCategoryOutput()
                            {
                                category_id = child.id,
                                name = child.name,
                                icon = HostHelper.GetImgUrl(child.icon),
                            };
                            goods.goods_categories.Add(category);
                        }
                    }
                    output.Add(goods);
                }

                result.code = 1;
                result.msg = "获取成功";
                result.data = output;
            }
            catch (Exception ex)
            {
                result.msg = ex.Message;
                result.code = 2;
                LogHelper.WriteLog(ex);
            }

            return result;
        }

        /// <summary>
        /// 获取普通商品列表（第2批）
        /// </summary>
        /// <param name="user_id">用户ID</param>
        /// <param name="goods_name">商品名称</param>
        /// <param name="sort">排序</param>
        /// <param name="category_id">商品分类ID 0=>所有商品</param>
        /// <param name="brand_id">品牌</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        [HttpGet]
        [Route("GetOrdinaryGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<GetGoodsListOutput>> GetOrdinaryGoods(int user_id = 0, string goods_name = "", int category_id = 0, int brand_id = 0, Sort sort = Sort.All, int page_index = 1, int page_size = 20)
        {
            if (!string.IsNullOrWhiteSpace(goods_name))
            {
                goods_name = System.Web.HttpUtility.UrlDecode(goods_name, System.Text.Encoding.GetEncoding("utf-8"));//将Url中的编码转换为简体汉字
            }
            return GetGoodsList(user_id, goods_name, 0, sort, 0, category_id, brand_id, GoodsType.Ordinary, MarketingType.All, page_index, page_size);
        }

        /// <summary>
        /// 获取会员专属商品列表（第2批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="goods_name"></param>
        /// <param name="category_id">商品分类ID 0=>所有商品</param>
        /// <param name="sort"></param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        [HttpGet]
        [Route("GetMemberGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<GetGoodsListOutput>> GetMemberGoods(int user_id = 0, string goods_name = "", int category_id = 0, Sort sort = Sort.DateDes, int page_index = 1, int page_size = 20)
        {
            return GetGoodsList(user_id, goods_name, 0, sort, 0, category_id, 0, GoodsType.Memeber, MarketingType.All, page_index, page_size);
        }

        /// <summary>
        /// 获取营销商品列表（第2批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="coupon_id">优惠券ID</param>
        /// <param name="marketing_type">营销类型</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        [HttpGet]
        [Route("GetMarketingGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<GetGoodsListOutput>> GetMarketingGoods(int user_id = 0, int coupon_id = 0, MarketingType marketing_type = MarketingType.All, int page_index = 1, int page_size = 20)
        {
            return GetGoodsList(user_id, "", coupon_id, Sort.All, 0, 0, 0, GoodsType.All, marketing_type, page_index, page_size);
        }

        /// <summary>
        /// 获取助力免单商品列表（第2批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="category_id">商品分类ID 0=>所有商品</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        [HttpGet]
        [Route("GetFreeGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<GetGoodsListOutput>> GetFreeGoods(int user_id = 0, int category_id = 0, int page_index = 1, int page_size = 20)
        {
            return GetGoodsList(user_id, "", 0, Sort.All, 0, category_id, 0, GoodsType.Free, MarketingType.All, page_index, page_size);
        }

        /// <summary>
        /// 获取1元购商品列表（第2批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="category_id">商品分类ID 0=>所有商品</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        [HttpGet]
        [Route("GetWelfareGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<GetGoodsListOutput>> GetWelfareGoods(int user_id = 0, int category_id = 0, int page_index = 1, int page_size = 20)
        {
            return GetGoodsList(user_id, "", 0, Sort.All, 0, category_id, 0, GoodsType.Welfare, MarketingType.All, page_index, page_size);
        }

        /// <summary>
        /// 获取店铺商品列表（第4批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="shop_id">店铺ID</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        [HttpGet]
        [Route("GetShopGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<GetGoodsListOutput>> GetShopGoods(int user_id = 0, int shop_id = 0, int page_index = 1, int page_size = 20)
        {
            return GetGoodsList(user_id, "", 0, Sort.All, shop_id, 0, 0, GoodsType.Ordinary, MarketingType.All, page_index, page_size);
        }

        /// <summary>
        /// 获取商品列表
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="goods_name"></param>
        /// <param name="coupon_id"></param>
        /// <param name="sort"></param>
        /// <param name="shop_id"></param>
        /// <param name="category_id">商品分类ID 0=>所有商品</param>
        /// <param name="brand_id"></param>
        /// <param name="goods_type">商品类型</param>
        /// <param name="marketing_type"></param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        private Response<IPagedList<GetGoodsListOutput>> GetGoodsList(int user_id = 0, string goods_name = "", int coupon_id = 0, Sort sort = Sort.All, int shop_id = 0, int category_id = 0, int brand_id = 0, GoodsType goods_type = GoodsType.Ordinary, MarketingType marketing_type = MarketingType.All, int page_index = 1, int page_size = 20)
        {
            Response<IPagedList<GetGoodsListOutput>> result = new Response<IPagedList<GetGoodsListOutput>>();
            result.code = 0;
            result.msg = "";
            result.data = null;

            try
            {
                var date = DateTime.Now;
                var goodsBank = db.gw_goods
                    .Include(g => g.gw_base_brand)
                    .Include(g => g.gw_goods_property)
                    .Include(g => g.gw_goods_picture)
                    .Include(g => g.gw_goods_sku)
                    .Include(g => g.gw_goods_collection)
                    .Include(g => g.gw_cart)
                    //.Include(g => g.gw_marketing_coupon)
                    .Where(g => g.deleted == false && g.gw_goods_property.published == 1 && !g.gw_shop.deleted && g.gw_shop.status == 1 && g.company_id == CompanyId);

                if (category_id != 0)
                {
                    goodsBank = goodsBank.Where(g => g.category_id == category_id || g.category_id1 == category_id || g.category_id2 == category_id);
                }

                if (brand_id != 0)
                {
                    goodsBank = goodsBank.Where(g => g.brand_id == brand_id);
                }

                //优惠券
                //var is_all = false;
                #region 优惠券
                //switch (goods_type)
                //{
                //    case GoodsType.Ordinary:
                //    case GoodsType.Memeber:
                //        if (coupon_id != 0)
                //        {
                //            var coupon = db.gw_marketing_coupons.Find(coupon_id);
                //            if (coupon.deleted == false && coupon.status == 1 && coupon.start_date <= date && coupon.end_date >= date && coupon.is_all)
                //            {
                //                is_all = true;

                //                if (coupon.type == 0)
                //                {
                //                    goods_type = GoodsType.All;
                //                }
                //                else if (coupon.type == 1)
                //                {
                //                    goods_type = GoodsType.Ordinary;
                //                }
                //                else
                //                {
                //                    goods_type = GoodsType.Memeber;
                //                }
                //            }

                //            if (!is_all)
                //            {
                //                goodsBank = goodsBank.Where(g => g.gw_marketing_coupon.Any(c => c.id == coupon_id));
                //            }
                //        }
                //        else
                //        {
                //            List<int> lst = new List<int>();
                //            lst.Add(0);
                //            if (goods_type == GoodsType.Memeber)
                //            {
                //                lst.Add(2);
                //                is_all = db.gw_marketing_coupons.Any(c => c.deleted == false && c.status == 1 && c.start_date <= date && c.end_date >= date && c.is_all && lst.Contains(c.type));
                //            }
                //            else if (goods_type == GoodsType.Ordinary)
                //            {
                //                lst.Add(1);
                //                is_all = db.gw_marketing_coupons.Any(c => c.deleted == false && c.status == 1 && c.start_date <= date && c.end_date >= date && c.is_all && lst.Contains(c.type));
                //            }
                //        }
                //        break;
                //    case GoodsType.Free:
                //    case GoodsType.Welfare:
                //        goodsBank = goodsBank.Where(g => g.gw_goods_rule_free.add_time < date && !g.deleted && g.gw_goods_rule_free.published && g.gw_goods_rule_free.is_sale);
                //        goodsBank = goodsBank.Where(g => (g.gw_goods_rule_free.end_time != null && g.gw_goods_rule_free.end_time > date) || g.gw_goods_rule_free.end_time == null);
                //        break;
                //}
                #endregion


                var sources = goodsBank.Select(g => new GetGoodsListOutput
                {
                    shop_id = g.shop_id,
                    category_id = (int)g.category_id,
                    goods_type = (GoodsType)g.type_id,
                    goods_id = g.id,
                    goods_name = g.name,
                    goods_spec = g.spec,
                    goods_brand = g.gw_base_brand.name,
                    goods_mnemonic = g.mnemonic,
                    sort = g.gw_goods_property.sort,
                    add_time = g.add_time,
                    market_price = g.gw_goods_property.market_price,
                    sale_price = g.gw_goods_property.sale_price,
                    picture_url = g.gw_goods_picture.FirstOrDefault(p => p.is_default == true && p.type == 0).url,
                    sale_count = g.gw_goods_property.sale_count,
                    is_top = g.gw_goods_property.is_top,
                    is_sale = g.gw_goods_property.is_sale,
                    is_new = g.gw_goods_property.is_new,
                    //goods_collection = g.gw_goods_collection.FirstOrDefault(c => c.user_id == user_id),
                    skus = g.gw_goods_sku
                           .Where(s => !s.deleted)
                           .Select(s => new SkuOutput()
                           {
                               sku_id = s.id,
                               is_sale = s.is_sale,
                               limit_quantity = s.limit_quantity,
                               market_price = s.market_price,
                               sale_price = s.sale_price,
                               cost_price = s.settlement_price,
                               json_specs = s.specs,
                               thumb_url = s.thumb_url,
                               quantity = 0,
                               conversion_rate = s.conversion_rate,
                           }).ToList(),
                    cart = g.gw_cart
                            .Where(c => c.user_id == user_id)
                            .Select(s => new CartOutput()
                            {
                                cart_id = s.id,
                                quantity = s.quantity,
                                sku_id = s.sku_id,
                            }).ToList(),
                    //_is_coupon = g.gw_marketing_coupon.Any(c => c.deleted == false && c.status == 1 && c.start_date <= date && c.end_date >= date) || is_all
                });
                if (goods_type != GoodsType.All)
                {
                    sources = sources.Where(g => g.goods_type == goods_type);
                }
                if (marketing_type == MarketingType.Coupon)
                {
                    sources = sources.Where(s => s._is_coupon == true);
                }
                if (shop_id != 0)
                {
                    sources = sources.Where(s => s.shop_id == shop_id);
                }
                if (!string.IsNullOrEmpty(goods_name))
                {
                    sources = sources.Where(s => s.goods_name.Contains(goods_name) || s.goods_mnemonic.Contains(goods_name));

                    gw_goods_search search = new gw_goods_search()
                    {
                        add_time = DateTime.Now,
                        search = goods_name,
                        user_id = user_id,
                    };
                    db.gw_goods_searches.Add(search);
                    db.SaveChanges();
                }

                switch (sort)
                {
                    case Sort.SalesDes:
                        sources = sources.OrderByDescending(g => g.sale_count);
                        break;
                    case Sort.SalesAsc:
                        sources = sources.OrderBy(g => g.sale_count);
                        break;
                    case Sort.New:
                        sources = sources.OrderByDescending(g => g.is_new).ThenByDescending(g => g.add_time);
                        break;
                    case Sort.DateDes:
                        sources = sources.OrderByDescending(g => g.add_time);
                        break;
                    case Sort.DateAsc:
                        sources = sources.OrderBy(g => g.add_time);
                        break;
                    case Sort.PriceDes:
                        sources = sources.OrderByDescending(g => g.sale_price);
                        break;
                    case Sort.PriceAsc:
                        sources = sources.OrderBy(g => g.sale_price);
                        break;
                    case Sort.Top:
                    default:
                        sources = sources.OrderByDescending(g => g.is_top).ThenByDescending(g => g.sort);
                        break;
                }

                IPagedList<GetGoodsListOutput> output = new PagedList<GetGoodsListOutput>(sources, page_index, page_size);
                result.code = 1;
                if (output == null || output.Count() == 0)
                {
                    result.msg = "没有更多商品了";
                    return result;
                }
                foreach (var item in output)
                {
                    //if (goods_type != GoodsType.Free)
                    //{
                    //    item.is_coupon = item._is_coupon;
                    //}
                    item.picture_url = HostHelper.GetImgUrl(item.picture_url);
                    //if (item.goods_collection != null)
                    //{
                    //    item.goods_collection_id = item.goods_collection.id;
                    //}

                    if (item.skus != null && item.skus.Count > 0)
                    {
                        foreach (var sku in item.skus)
                        {
                            if (item.cart != null)
                            {
                                var cart = item.cart.FirstOrDefault(c => c.sku_id == sku.sku_id);
                                if (cart != null)
                                {
                                    sku.quantity = cart.quantity;
                                    sku.cart_id = cart.cart_id;
                                }
                            }
                            sku.thumb_url = HostHelper.GetImgUrl(sku.thumb_url);
                            sku.specs = JsonConvert.DeserializeObject<List<SpecOutput>>(sku.json_specs);
                        }
                    }
                }

                result.msg = "获取成功";
                result.data = output;
            }
            catch (Exception ex)
            {
                result.msg = ex.Message;
                result.code = 2;
                LogHelper.WriteLog(ex);
            }

            return result;
        }

        #endregion

        #region 商品详情
        /// <summary>
        /// 获取商品详情（第2批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="goods_id">商品ID</param>
        [HttpGet]
        [Route("GetGoods")]
        [CacheOutput(ClientTimeSpan = 1, ServerTimeSpan = 1)]
        public async Task<Response<GetGoodsOutput>> GetGoods(int goods_id, int user_id = 0)
        {
            Response<GetGoodsOutput> result = new Response<GetGoodsOutput>();
            result.code = 0;
            result.msg = "";
            result.data = null;

            try
            {
                string error;
                if (!goodsService.IsBuyGoods(goods_id, out error))
                {
                    result.msg = error;
                    return result;
                }

                var date = DateTime.Now;
                var output = db.gw_goods
                   .Include(g => g.gw_base_brand)
                   .Include(g => g.gw_goods_category)
                   .Include(g => g.gw_goods_picture)
                   .Include(g => g.gw_goods_property)
                   .Include(g => g.gw_goods_sku)
                   .Include(g => g.gw_goods_collection)
                   .Include(g => g.gw_marketing_coupon)
                   .Include(g => g.gw_goods_service)
                   .Include(g => g.gw_cart)
                   .Where(g => g.id == goods_id && g.company_id == CompanyId)
                   .Select(g => new GetGoodsOutput()
                   {
                       _deleted = g.deleted,
                       _published = g.gw_goods_property.published,
                       category_id = (int)g.category_id,
                       description = g.description,
                       detail_pictures = g.gw_goods_picture.Where(p => p.type == 1).OrderBy(p => p.sort).Select(p => p.url).ToList(),
                       goods_id = g.id,
                       goods_type = (GoodsType)g.type_id,
                       name = g.name,
                       goods_spec = g.spec,
                       goods_brand = g.gw_base_brand.name,
                       goods_mnemonic = g.mnemonic,
                       short_title = g.short_title,
                       market_price = g.gw_goods_property.market_price,
                       sale_price = g.gw_goods_property.sale_price,
                       cost_price = g.gw_goods_property.settlement_price,
                       comment_count = g.gw_goods_property.comment_count,
                       freight_template_id = g.freight_template_id,
                       summary = g.summary,
                       weight = g.weight,
                       volume = g.volume,
                       shop = new ShopOutput()
                       {
                           shop_id = g.shop_id,
                           //shop_logo = g.gw_shop.logo,
                           //shop_name = g.gw_shop.name,
                           //mobile = g.gw_shop.mobile,
                           //qq = g.gw_shop.qq,
                           //telephone = g.gw_shop.telephone,
                           //wechat = g.gw_shop.wechat,
                           //goods_count = g.gw_shop.gw_shop_property.goods_count,
                           //order_count = g.gw_shop.gw_shop_property.order_count,
                       },
                       top_pictures = g.gw_goods_picture.Where(p => p.type == 0)
                       .OrderBy(p => p.sort)
                       .Select(p => p.url).ToList(),
                       goods_collection = g.gw_goods_collection.FirstOrDefault(c => c.user_id == user_id),
                       skus = g.gw_goods_sku.Where(s => !s.deleted)
                       .Select(s => new SkuOutput()
                       {
                           sku_id = s.id,
                           is_sale = s.is_sale,
                           limit_quantity = s.limit_quantity,
                           market_price = s.market_price,
                           sale_price = s.sale_price,
                           cost_price = s.settlement_price,
                           json_specs = s.specs,
                           thumb_url = s.thumb_url,
                           conversion_rate = s.conversion_rate,
                       }).ToList(),
                       services = g.gw_goods_service.OrderBy(s => s.sort)
                       .Select(s => new ServiceOutput()
                       {
                           title = s.title,
                           content = s.content,
                           sort = s.sort,
                       }).ToList(),
                       coupons = g.gw_marketing_coupon.Where(c => c.deleted == false && c.status == 1 && c.start_date <= date && c.end_date >= date)
                       .Select(c => new GetCouponOutput()
                       {
                           coupon_id = c.id,
                           name = c.name,
                           total_quantity = c.total_quantity,
                           remain_quantity = c.remain_quantity,
                           amount = c.amount,
                           value = c.value,
                           coupon_type = (CouponType)c.type,
                           _end_date = c.end_date,
                           _start_date = c.start_date,
                       }).ToList(),
                       cart = g.gw_cart
                        .Where(c => c.user_id == user_id)
                        .Select(s => new CartOutput()
                        {
                            cart_id = s.id,
                            quantity = s.quantity,
                            sku_id = s.sku_id,
                        }).ToList(),
                   })
                   .FirstOrDefault();

                if (output == null || output._deleted || output._published != 1)
                {
                    result.msg = "商品已下架";
                    return result;
                }

                #region 添加SKU
                if (output.skus == null || output.skus.Count == 0)
                {
                    result.msg = "SKU不存在";
                    return result;
                }


                if (output.skus != null && output.skus.Count > 0)
                {
                    bool isSave = false;
                    foreach (var sku in output.skus)
                    {
                        try
                        {
                            //if (string.IsNullOrEmpty(item.json_specs))
                            //{
                            //    var sku = await db.gw_goods_skus
                            //                .Include(s => s.gw_goods_spec_value)
                            //                .FirstOrDefaultAsync(s => s.id == item.sku_id);

                            //    //var gw_goods_spec_values = db.gw_goods_spec_values
                            //    //     .Include(v => v.gw_goods_spec)
                            //    //     .OrderBy(v => v.spec_id).ThenBy(v => v.sort);

                            //    var gw_goods_spec_values = sku.gw_goods_spec_value
                            //                .OrderBy(v => v.spec_id).ThenBy(v => v.sort)
                            //                .ToList();

                            //    List<SpecOutput> lstSpec = new List<SpecOutput>();
                            //    foreach (var itemspec in gw_goods_spec_values)
                            //    {
                            //        SpecOutput spec = new SpecOutput()
                            //        {
                            //            spec_key = itemspec.gw_goods_spec.name,
                            //            spec_value = itemspec.name,
                            //        };
                            //        lstSpec.Add(spec);
                            //    }
                            //    item.sale_price = 0;
                            //    sku.specs = JsonConvert.SerializeObject(lstSpec);
                            //    db.Entry(sku).Property(s => s.specs).IsModified = true;
                            //    item.json_specs = sku.specs;
                            //    isSave = true;
                            //}

                            if (output.cart != null)
                            {
                                var cart = output.cart.FirstOrDefault(c => c.sku_id == sku.sku_id);
                                if (cart != null)
                                {
                                    sku.quantity = cart.quantity;
                                    sku.cart_id = cart.cart_id;
                                }
                            }
                            sku.specs = JsonConvert.DeserializeObject<List<SpecOutput>>(sku.json_specs);

                        }
                        catch (Exception ex)
                        {
                            LogHelper.WriteLog(ex);
                        }
                    }

                    if (isSave)
                    {
                        await db.SaveChangesAsync();
                    }

                }
                #endregion

                #region 收藏

                if (output.goods_collection != null)
                {
                    output.goods_collection_id = output.goods_collection.id;
                }

                #endregion

                //服务器时间
                output.server_time = TimeHelper.GetTimeStamp();

                //优惠券
                #region 优惠券
                //List<int> lstCouponType = new List<int>();
                //lstCouponType.Add((int)CouponType.All);
                //if (output.goods_type == GoodsType.Memeber)
                //{
                //    lstCouponType.Add((int)CouponType.Memeber);
                //}
                //else if (output.goods_type == GoodsType.Ordinary)
                //{
                //    lstCouponType.Add((int)CouponType.Ordinary);
                //}

                //var coupons = await db.gw_marketing_coupons
                //    .Where(c => c.deleted == false && c.status == 1 && c.start_date <= date && c.end_date >= date && c.is_all && lstCouponType.Contains(c.type))
                //    .Select(c => new GetCouponOutput()
                //    {
                //        coupon_id = c.id,
                //        name = c.name,
                //        total_quantity = c.total_quantity,
                //        remain_quantity = c.remain_quantity,
                //        amount = c.amount,
                //        value = c.value,
                //        coupon_type = (CouponType)c.type,
                //        _end_date = c.end_date,
                //        _start_date = c.start_date,
                //    }).ToListAsync();

                //if (coupons != null && coupons.Count > 0)
                //{
                //    output.coupons.AddRange(coupons);
                //}

                //if (output.coupons != null && output.coupons.Count > 0)
                //{
                //    output.is_coupon = true;
                //    foreach (var item in output.coupons)
                //    {
                //        item.end_date = TimeHelper.GetTimeStamp(item._end_date);
                //        item.start_date = TimeHelper.GetTimeStamp(item._start_date);
                //    }
                //}
                #endregion

                //商品评论
                var commentsSources = db.gw_goods_comments
                    .Where(t => t.goods_id == goods_id && t.deleted == false && t.status == 1)
                    .Select(c => new CommentOutput()
                    {
                        comment_id = c.id,
                        add_time = c.add_time,
                        comment_pictures = c.gw_goods_comment_picture.Select(p => p.url).ToList(),
                        nick_name = c.nick_name,
                        no_total = c.no_total,
                        rating = c.description_mark,
                        reply = c.reply,
                        review = c.review,
                        json_sku_specs = c.sku_specs,
                        yes_total = c.yes_total,
                        sort = c.sort,
                        user_logo = c.gw_user.logo,
                    });

                commentsSources = commentsSources.OrderBy(g => g.sort).ThenByDescending(c => c.add_time);
                IPagedList<CommentOutput> CommentPagedList = new PagedList<CommentOutput>(commentsSources, 1, 2);
                output.comment_count = CommentPagedList.TotalCount;
                output.comments = CommentPagedList.ToList();
                if (CommentPagedList != null && CommentPagedList.Count > 0)
                {
                    foreach (var item in output.comments)
                    {
                        try
                        {
                            item.nick_name = StringHelper.HideMiddleName(item.nick_name);
                            item.comment_time = TimeHelper.GetTimeStamp(item.add_time);
                            item.sku_specs = JsonConvert.DeserializeObject<List<SpecOutput>>(item.json_sku_specs);
                        }
                        catch (Exception)
                        {

                        }
                    }
                }

                //图片
                if (output.detail_pictures != null && output.detail_pictures.Count > 0)
                {
                    output.detail_pictures = HostHelper.GetImgUrl(output.detail_pictures);
                }
                if (output.top_pictures != null && output.top_pictures.Count > 0)
                {
                    output.top_pictures = HostHelper.GetImgUrl(output.top_pictures);
                }
                if (output.skus != null && output.skus.Count > 0)
                {
                    foreach (var item in output.skus)
                    {
                        item.thumb_url = HostHelper.GetImgUrl(item.thumb_url);
                    }
                }

                result.code = 1;
                result.data = output;

                //用户浏览
                gw_goods_view goods_view = new gw_goods_view()
                {
                    add_time = DateTime.Now,
                    goods_id = goods_id,
                    user_id = user_id,
                };

                db.gw_goods_views.Add(goods_view);
                await db.SaveChangesAsync();

                return result;
            }
            catch (Exception ex)
            {
                result.msg = ex.Message;
                result.code = 2;
                LogHelper.WriteLog(ex);
            }

            return result;
        }

        #endregion

        #region 商品标签
        /// <summary>
        /// 获得商品标签（第3批）
        /// </summary>
        /// <param name="goods_id">商品ID</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetTags")]
        public async Task<Response<List<TagOutput>>> GetTags(int goods_id)
        {
            Response<List<TagOutput>> result = new Response<List<TagOutput>>();
            result.code = 0;
            result.msg = "";

            try
            {
                var tags = await db.gw_goods_tags.OrderByDescending(t => t.number).Where(t => t.goods_id == goods_id && t.positive > 0).Select(t => new TagOutput
                {
                    tag_id = t.id,
                    name = t.name,
                    number = t.number,
                    positive = t.positive,
                }).Take(5).ToListAsync();

                result.code = 1;
                result.data = tags;
            }
            catch (Exception ex)
            {
                result.code = 2;
                result.msg = ex.ToString();
                LogHelper.WriteLog(ex);
            }
            return result;
        }
        #endregion

        #region 商品评论
        /// <summary>
        /// 获得商品评论（第3批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="goods_id">商品ID</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetComments")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public Response<IPagedList<CommentOutput>> GetComments(int user_id = 0, int goods_id = 0, int page_index = 1, int page_size = 20)
        {
            Response<IPagedList<CommentOutput>> result = new Response<IPagedList<CommentOutput>>();
            result.code = 0;
            result.msg = "";

            try
            {
                //商品评论
                var commentsSources = db.gw_goods_comments
                    .Include(c => c.gw_user)
                    .Where(t => t.goods_id == goods_id && t.deleted == false && t.status == 1)
                    .Select(c => new CommentOutput()
                    {
                        comment_id = c.id,
                        add_time = c.add_time,
                        comment_pictures = c.gw_goods_comment_picture.Select(p => p.url).ToList(),
                        nick_name = c.nick_name,
                        no_total = c.no_total,
                        rating = c.description_mark,
                        reply = c.reply,
                        review = c.review,
                        json_sku_specs = c.sku_specs,
                        yes_total = c.yes_total,
                        sort = c.sort,
                        user_logo = c.gw_user.logo,
                    });

                commentsSources = commentsSources.OrderBy(g => g.sort).ThenByDescending(c => c.add_time);
                IPagedList<CommentOutput> CommentPagedList = new PagedList<CommentOutput>(commentsSources, page_index, page_size);

                if (CommentPagedList != null && CommentPagedList.Count > 0)
                {
                    foreach (var item in CommentPagedList)
                    {
                        try
                        {
                            item.nick_name = StringHelper.HideMiddleName(item.nick_name);

                            item.comment_time = TimeHelper.GetTimeStamp(item.add_time);
                            item.sku_specs = JsonConvert.DeserializeObject<List<SpecOutput>>(item.json_sku_specs);
                        }
                        catch (Exception)
                        {

                        }
                    }
                }
                result.code = 1;
                result.data = CommentPagedList;
            }
            catch (Exception ex)
            {
                result.code = 2;
                result.msg = ex.ToString();
                LogHelper.WriteLog(ex);
            }
            return result;
        }
        #endregion

        #region 拼单
        /// <summary>
        /// 商品正在拼单（第4批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="goods_id">商品ID</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetOrderGroupsByGoods")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        private Response<IPagedList<OrderGroup>> GetOrderGroupsByGoods(int user_id = 0, int goods_id = 0, int page_index = 1, int page_size = 20)
        {
            return GetOrderGroups(0, goods_id, page_index, page_size);
        }

        /// <summary>
        /// 店铺商品正在拼单（第4批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="shop_id">商铺ID</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetOrderGroupsByShop")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        private Response<IPagedList<OrderGroup>> GetOrderGroupsByShop(int user_id = 0, int shop_id = 0, int page_index = 1, int page_size = 20)
        {
            return GetOrderGroups(shop_id, 0, page_index, page_size);
        }

        /// <summary>
        /// 正在拼单（第4批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="shop_id">商铺ID</param>
        /// <param name="goods_id">商品ID</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        /// <returns></returns>
        private Response<IPagedList<OrderGroup>> GetOrderGroups(int user_id = 0, int shop_id = 0, int goods_id = 0, int page_index = 1, int page_size = 20)
        {
            Response<IPagedList<OrderGroup>> result = new Response<IPagedList<OrderGroup>>();
            result.code = 0;
            result.msg = "";

            try
            {
                var now = DateTime.Now;

                //优惠券
                List<int> lst = new List<int>();
                lst.Add(0);
                lst.Add(1);
                var is_all = db.gw_marketing_coupons.Any(c => c.deleted == false && c.status == 1 && c.start_date <= now && c.end_date >= now && c.is_all && lst.Contains(c.type));

                var orderGroups = db.gw_order_groups
                    .Include(g => g.gw_order_group_user)
                    .Include(g => g.gw_goods)
                    .Include(g => g.gw_goods.gw_goods_property)
                    .Include(g => g.gw_goods.gw_marketing_coupon)
                    .Include(g => g.gw_goods.gw_marketing_returned)
                    .Where(g => g.status == (byte)GroupStatus.Process && g.expire_time > now && g.group_type == (int)GroupType.Lucky)
                    .Select(g => new OrderGroup
                    {
                        require_num = g.require_num,
                        red_packet = g.red_packet,
                        status = g.status,
                        order_group_id = g.id,
                        order_group_no = g.group_no,
                        _add_time = g.add_time,
                        _expire_time = g.expire_time,
                        group_type = GroupType.Lucky,
                        is_red_packet = false,

                        goods = new GroupGoodsOutput()
                        {
                            shop_id = g.gw_goods.shop_id,
                            goods_id = g.gw_goods.id,
                            goods_name = g.gw_goods.name,
                            goods_type = (GoodsType)g.gw_goods.type_id,
                            picture_url = g.gw_goods.gw_goods_picture.FirstOrDefault().url,
                            sale_count = g.gw_goods.gw_goods_property.sale_count,
                            sale_price = g.gw_goods.gw_goods_property.sale_price,
                            market_price = g.gw_goods.gw_goods_property.market_price,
                        },

                        is_returned = g.gw_goods.gw_marketing_returned.Any(c => c.status == 1 && c.start_time <= now && c.end_time >= now),
                        is_coupon = g.gw_goods.gw_marketing_coupon.Any(c => c.deleted == false && c.status == 1 && c.start_date <= now && c.end_date >= now) || is_all,

                        group_users = g.gw_order_group_user.Select(u => new GroupUser
                        {
                            user_id = u.user_id,
                            is_award = u.is_award,
                            is_leader = u.is_leader,
                            logo = u.gw_user.logo,
                            mobile = u.gw_user.name,
                            nick_name = u.gw_user.nick_name,
                        }).ToList()
                    });
                if (shop_id != 0)
                {
                    orderGroups = orderGroups.Where(g => g.goods.shop_id == shop_id);
                }

                if (goods_id != 0)
                {
                    orderGroups = orderGroups.Where(g => g.goods.goods_id == goods_id);
                }

                orderGroups = orderGroups.OrderBy(c => c._expire_time);
                IPagedList<OrderGroup> GroupPagedList = new PagedList<OrderGroup>(orderGroups, page_index, page_size);

                if (GroupPagedList != null && GroupPagedList.Count > 0)
                {
                    foreach (var item in GroupPagedList)
                    {
                        item.expire_time = TimeHelper.GetTimeStamp(item._expire_time);
                        item.group_status = (GroupStatus)item.status;
                        item.goods.picture_url = HostHelper.GetImgUrl(item.goods.picture_url);
                        item.users_num = item.group_users.Count;

                        foreach (var group_user in item.group_users)
                        {
                            if (group_user.is_leader)
                            {
                                item.user_id = group_user.user_id;
                                item.logo = group_user.logo;
                                item.nick_name = group_user.nick_name == null ? StringHelper.HideMobile(group_user.mobile) : group_user.nick_name;
                            }
                            group_user.nick_name = group_user.nick_name == null ? StringHelper.HideMobile(group_user.mobile) : group_user.nick_name;
                        }

                        item.shop_id = item.goods.shop_id;
                        item.goods_id = item.goods.goods_id;
                        item.goods_name = item.goods.goods_name;
                        item.picture_url = item.goods.picture_url;
                        item.sale_count = item.goods.sale_count;
                        item.sale_price = item.goods.sale_price;

                        item.goods.is_coupon = item.is_coupon;
                        item.goods.is_returned = item.is_returned;
                    }
                }
                result.code = 1;
                result.data = GroupPagedList;
            }
            catch (Exception ex)
            {
                result.code = 2;
                result.msg = ex.ToString();
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        /// <summary>
        /// 正在拼单（第4批）
        /// </summary>
        /// <param name="user_id"></param>
        /// <param name="order_group_id">拼单ID</param>
        /// <param name="order_group_no">拼单号</param>
        /// <param name="order_no">订单号</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetOrderGroup")]
        [CacheOutput(ClientTimeSpan = CACHETIME, ServerTimeSpan = CACHETIME)]
        public async Task<Response<OrderGroup>> GetOrderGroup(int user_id = 0, string order_group_no = "", int order_group_id = 0, string order_no = "")
        {
            Response<OrderGroup> result = new Response<OrderGroup>();
            result.code = 0;
            result.msg = "";

            try
            {
                if (!string.IsNullOrEmpty(order_no))
                {
                    var order = await db.gw_orders
                        .FirstOrDefaultAsync(o => o.order_no == order_no);

                    if (order != null && order.order_group_id > 0)
                    {
                        order_group_id = (int)order.order_group_id;
                    }
                }

                var now = DateTime.Now;
                var source = db.gw_order_groups
                    .Include(g => g.gw_order_group_user)
                    .Include(g => g.gw_goods)
                    .Include(g => g.gw_goods.gw_shop)
                    .Include(g => g.gw_goods.gw_goods_sku)
                    .Include(g => g.gw_goods.gw_goods_property);

                if (!string.IsNullOrEmpty(order_group_no))
                {
                    source = source.Where(g => g.group_no == order_group_no);
                }
                else
                {
                    source = source.Where(g => g.id == order_group_id);
                }

                var orderGroup = source
                .Select(g => new OrderGroup
                {
                    order_group_id = g.id,
                    order_group_no = g.group_no,
                    require_num = g.require_num,
                    red_packet = g.red_packet,
                    _add_time = g.add_time,
                    _expire_time = g.expire_time,
                    _cancel_time = g.cancel_time,
                    _complete_time = g.complete_time,
                    group_type = (GroupType)g.group_type,
                    group_status = (GroupStatus)g.status,
                    is_red_packet = g.is_red_packet,
                    shop = new ShopOutput()
                    {
                        shop_id = g.gw_goods.gw_shop.id,
                        shop_logo = g.gw_goods.gw_shop.logo,
                        shop_name = g.gw_goods.gw_shop.name,
                        mobile = g.gw_goods.gw_shop.mobile,
                        qq = g.gw_goods.gw_shop.qq,
                        telephone = g.gw_goods.gw_shop.telephone,
                        wechat = g.gw_goods.gw_shop.wechat,

                    },
                    goods = new GroupGoodsOutput()
                    {
                        shop_id = g.gw_goods.shop_id,
                        goods_id = g.gw_goods.id,
                        goods_name = g.gw_goods.name,
                        summary = g.gw_goods.summary,
                        picture_url = g.gw_goods.gw_goods_picture.FirstOrDefault(p => p.is_default).url,
                        sale_count = g.gw_goods.gw_goods_property.sale_count,
                        sale_price = g.gw_goods.gw_goods_property.sale_price,
                        market_price = g.gw_goods.gw_goods_property.market_price,
                        weight = g.gw_goods.weight,
                        volume = g.gw_goods.volume,
                        freight_template_id = g.gw_goods.freight_template_id,
                        skus = g.gw_goods.gw_goods_sku.Where(s => !s.deleted)
                               .Select(s => new SkuOutput()
                               {
                                   sku_id = s.id,
                                   is_sale = s.is_sale,
                                   limit_quantity = s.limit_quantity,
                                   market_price = s.market_price,
                                   sale_price = s.sale_price,
                                   json_specs = s.specs,
                                   thumb_url = s.thumb_url,
                               }).ToList(),
                    },
                    group_users = g.gw_order_group_user
                                .OrderByDescending(u => u.is_leader)
                                .Select(u => new GroupUser
                                {
                                    user_id = u.user_id,
                                    is_award = u.is_award,
                                    is_leader = u.is_leader,
                                    logo = u.gw_user.logo,
                                    mobile = u.gw_user.name,
                                    help_state = u.help_status,
                                    nick_name = u.gw_user.nick_name,
                                }).ToList()
                }).FirstOrDefault();

                if (orderGroup != null)
                {
                    if (orderGroup.goods != null)
                    {
                        orderGroup.goods.picture_url = HostHelper.GetImgUrl(orderGroup.goods.picture_url);
                        //SKU
                        foreach (var item in orderGroup.goods.skus)
                        {
                            item.thumb_url = HostHelper.GetImgUrl(item.thumb_url);
                            item.specs = JsonConvert.DeserializeObject<List<SpecOutput>>(item.json_specs);
                        }
                        if (orderGroup.group_type == GroupType.Welfare)
                        {
                            orderGroup.goods.sale_price = 1;
                        }
                        else if (orderGroup.group_type == GroupType.Free)
                        {
                            orderGroup.goods.sale_price = 0;
                        }
                    }
                    orderGroup.expire_time = TimeHelper.GetTimeStamp(orderGroup._expire_time);
                    orderGroup.add_time = TimeHelper.GetTimeStamp(orderGroup._add_time);
                    if (orderGroup._cancel_time != null)
                    {
                        orderGroup.cancel_time = TimeHelper.GetTimeStamp(orderGroup._cancel_time);
                    }
                    if (orderGroup._complete_time != null)
                    {
                        orderGroup.complete_time = TimeHelper.GetTimeStamp(orderGroup._complete_time);
                    }
                    orderGroup.users_num = orderGroup.group_users.Count;
                    if (orderGroup.group_type == GroupType.Free)
                    {
                        //自己不算
                        orderGroup.users_num -= 1;
                    }
                    //过期
                    if (orderGroup.group_status == GroupStatus.Process && DateTime.Now > orderGroup._expire_time)
                    {
                        orderGroup.group_status = GroupStatus.Failure;
                    }

                    if (orderGroup.shop != null)
                    {
                        orderGroup.shop.shop_logo = HostHelper.GetImgUrl(orderGroup.shop.shop_logo);
                    }


                    foreach (var group_user in orderGroup.group_users)
                    {
                        group_user.logo = group_user.logo == null ? HostHelper.GetImgUrl("") : group_user.logo;
                        group_user.nick_name = group_user.nick_name == null ? StringHelper.HideMobile(group_user.mobile) : group_user.nick_name;
                    }
                }
                result.code = 1;
                result.data = orderGroup;
            }
            catch (Exception ex)
            {
                result.code = 2;
                result.msg = ex.ToString();
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        #endregion

        #region 商品收藏
        /// <summary>
        /// 添加商品收藏（第4批）
        /// </summary>
        [HttpPost]
        [Route("AddGoodsCollection")]
        public async Task<Response<GoodsCollectionOutput>> AddGoodsCollection(AddGoodsCollection input)
        {
            Response<GoodsCollectionOutput> result = new Response<GoodsCollectionOutput>();
            result.code = 0;
            result.msg = "";
            try
            {
                var goods = await db.gw_goods
                    .Include(g => g.gw_goods_property)
                    .FirstOrDefaultAsync(g => g.id == input.goods_id);
                if (goods == null || goods.deleted)
                {
                    result.msg = "商品不存在";
                    return result;
                }
                if (goods.gw_goods_property.published != 1)
                {
                    result.msg = "商品已下架";
                    return result;
                }

                var goods_collection = await db.gw_goods_collections.FirstOrDefaultAsync(c => c.goods_id == input.goods_id && c.user_id == input.user_id);

                if (goods_collection != null)
                {
                    result.code = 1;
                    result.msg = "已收藏";
                    GoodsCollectionOutput output = new GoodsCollectionOutput() { goods_collection_id = goods_collection.id, goods_id = goods_collection.goods_id };

                    result.data = output;
                    return result;
                }

                goods_collection = new gw_goods_collection()
                {
                    add_time = DateTime.Now,
                    goods_id = input.goods_id,
                    user_id = input.user_id,
                };

                db.gw_goods_collections.Add(goods_collection);

                int row = await db.SaveChangesAsync();
                if (row > 0)
                {
                    result.code = 1;
                    result.msg = "收藏成功";
                    GoodsCollectionOutput output = new GoodsCollectionOutput() { goods_collection_id = goods_collection.id, goods_id = goods_collection.goods_id };
                    result.data = output;
                }
            }
            catch (Exception ex)
            {
                result.msg = ex.Message;
                result.code = 2;
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        /// <summary>
        /// 取消商品收藏（第4批）
        /// </summary>
        [HttpPost]
        [Route("DeleteGoodsCollection")]
        public async Task<Response<bool>> DeleteGoodsCollection(DeleteGoodsCollection input)
        {
            Response<bool> result = new Response<bool>();
            result.code = 0;
            result.msg = "";
            result.data = false;
            try
            {
                var goods_collection = await db.gw_goods_collections.FindAsync(input.goods_collection_id);
                if (goods_collection == null)
                {
                    result.code = 1;
                    result.msg = "已取消";
                    return result;
                }
                if (goods_collection.user_id != input.user_id)
                {
                    result.msg = "非法用户";
                    return result;
                }
                db.gw_goods_collections.Remove(goods_collection);
                await db.SaveChangesAsync();

                result.code = 1;
                result.msg = "取消成功";
                result.data = true;
            }
            catch (Exception ex)
            {
                result.msg = ex.Message;
                result.code = 2;
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        /// <summary>
        /// 获得收藏的商品(第4批)
        /// </summary>
        /// <param name="user_id">用户ID</param>
        /// <param name="page_index">页码</param>
        /// <param name="page_size">页数</param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetGoodsCollection")]
        public Response<IPagedList<GetGoodsListOutput>> GetGoodsCollection(int user_id, int page_index = 1, int page_size = 20)
        {
            Response<IPagedList<GetGoodsListOutput>> result = new Response<IPagedList<GetGoodsListOutput>>();
            result.code = 0;
            result.msg = "";

            try
            {
                var sources = db.gw_goods_collections
                    .Include(c => c.gw_goods)
                    .Include(c => c.gw_goods.gw_goods_property)
                    .Include(c => c.gw_goods.gw_goods_picture)
                    .Include(g => g.gw_goods.gw_base_brand)
                    .Include(g => g.gw_goods.gw_goods_sku)
                    .Include(g => g.gw_goods.gw_cart)
                    .Where(c => c.user_id == user_id)
                    .Select(g => new GetGoodsListOutput()
                    {
                        shop_id = g.gw_goods.shop_id,
                        category_id = (int)g.gw_goods.category_id,
                        goods_type = (GoodsType)g.gw_goods.type_id,
                        goods_id = g.gw_goods.id,
                        goods_name = g.gw_goods.name,
                        goods_spec = g.gw_goods.spec,
                        goods_brand = g.gw_goods.gw_base_brand.name,
                        goods_mnemonic = g.gw_goods.mnemonic,
                        sort = g.gw_goods.gw_goods_property.sort,
                        add_time = g.gw_goods.add_time,
                        market_price = g.gw_goods.gw_goods_property.market_price,
                        sale_price = g.gw_goods.gw_goods_property.sale_price,
                        picture_url = g.gw_goods.gw_goods_picture.FirstOrDefault(p => p.is_default == true && p.type == 0).url,
                        sale_count = g.gw_goods.gw_goods_property.sale_count,
                        is_top = g.gw_goods.gw_goods_property.is_top,
                        is_sale = g.gw_goods.gw_goods_property.is_sale,
                        is_new = g.gw_goods.gw_goods_property.is_new,
                        goods_collection_id = g.id,
                        skus = g.gw_goods.gw_goods_sku
                           .Where(s => !s.deleted)
                           .Select(s => new SkuOutput()
                           {
                               sku_id = s.id,
                               is_sale = s.is_sale,
                               limit_quantity = s.limit_quantity,
                               market_price = s.market_price,
                               sale_price = s.sale_price,
                               cost_price = s.settlement_price,
                               json_specs = s.specs,
                               thumb_url = s.thumb_url,
                               quantity = 0,
                           }).ToList(),
                        cart = g.gw_goods.gw_cart
                            .Where(c => c.user_id == user_id)
                            .Select(s => new CartOutput()
                            {
                                cart_id = s.id,
                                quantity = s.quantity,
                                sku_id = s.sku_id,
                            }).ToList(),
                    });

                sources = sources.OrderByDescending(s => s.goods_id);
                IPagedList<GetGoodsListOutput> pageList = new PagedList<GetGoodsListOutput>(sources, page_index, page_size);
                if (pageList != null)
                {
                    foreach (var item in pageList)
                    {
                        item.picture_url = HostHelper.GetImgUrl(item.picture_url);

                        foreach (var sku in item.skus)
                        {
                            if (item.cart != null)
                            {
                                var cart = item.cart.FirstOrDefault(c => c.sku_id == sku.sku_id);
                                if (cart != null)
                                {
                                    sku.quantity = cart.quantity;
                                    sku.cart_id = cart.cart_id;
                                }
                            }
                            sku.thumb_url = HostHelper.GetImgUrl(sku.thumb_url);
                            sku.specs = JsonConvert.DeserializeObject<List<SpecOutput>>(sku.json_specs);
                        }
                    }
                }
                result.data = pageList;
                result.code = 1;
            }
            catch (Exception ex)
            {
                result.code = 2;
                result.msg = ex.ToString();
                LogHelper.WriteLog(ex);
            }
            return result;
        }

        #endregion

    }
}
